package com.spzx.product.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.spzx.common.core.constant.SecurityConstants;
import com.spzx.common.core.domain.R;
import com.spzx.common.core.web.controller.BaseController;
import com.spzx.common.core.web.domain.AjaxResult;
import com.spzx.common.core.web.page.TableDataInfo;
import com.spzx.common.log.annotation.Log;
import com.spzx.common.redis.cache.GuiguCache;
import com.spzx.common.security.annotation.InnerAuth;
import com.spzx.product.domain.*;
import com.spzx.product.mapper.ProductDetailsMapper;
import com.spzx.product.mapper.SkuStockMapper;
import com.spzx.product.service.ProductDetailsService;
import com.spzx.product.service.ProductService;
import com.spzx.product.service.ProductSkuService;
import com.spzx.product.service.SkuStockService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.Predicate;

/**
 * 商品Controller
 */
@Tag(name = "商品接口管理")
@RestController
@RequestMapping("/product")
public class ProductController extends BaseController {

    @Resource
    private ProductService productService;
    @Autowired
    private ProductSkuService productSkuService;
    @Autowired
    private ProductDetailsService productDetailsService;
    @Autowired
    private SkuStockService skuStockService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Resource
    private SkuStockMapper skuStockMapper;

    @Operation(summary = "获取销量好的sku")
    @GetMapping("getTopSale")
    public R<List<ProductSku>> getTopSale() {
        return R.ok(productService.getTopSale());
    }

    //添加
    @PostMapping("/add")
    public AjaxResult add(@RequestBody Product product) {
        return toAjax(productService.insertProduct(product));
    }

    /**
     * 查询商品列表
     */
    @Operation(summary = "查询商品列表")
    @GetMapping("/list")
    public TableDataInfo list(Product product) {
        startPage();
        List<Product> list = productService.selectProductList(product);
        return getDataTable(list);
    }

    /**
     * 获取商品详细信息
     */
    @Operation(summary = "获取商品详细信息")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id) {
        return success(productService.selectProductById(id));
    }

    /**
     * 修改商品
     * @param product
     * @return
     */
    @Operation(summary = "修改商品")
    @PutMapping
    public AjaxResult edit(@RequestBody Product product) {
        return toAjax(productService.updateProduct(product));
    }

    /**
     * 删除商品
     *
     * @param ids
     * @return
     */
    @Operation(summary = "删除商品")
    @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids) {
        return toAjax(productService.deleteProductByIds(ids));
    }

    //远程调用使用，商品列表
    @GetMapping("/skuList/{pageNum}/{pageSize}")
    public R<TableDataInfo> skuList(@PathVariable Integer pageNum,
                                    @PathVariable Integer pageSize,
                                    @ModelAttribute SkuQuery skuQuery) {
        //设置分页参数
        PageHelper.startPage(pageNum,pageSize);
        //调用service方法根据条件查询
        List<ProductSku> list = productService.selectProductSkuList(skuQuery);

        TableDataInfo dataTable = getDataTable(list);
        return R.ok(dataTable);
    }

    //审核通过商品
    @GetMapping("/updateAuditStatus/{id}/{status}")
    public R updateAuditStatus(@PathVariable Long id, @PathVariable Integer status){
        Product product = new Product();
        product.setId(id);
        product.setAuditStatus(status);
        productService.updateById( product);
        return R.ok();
    }

    //上架商品
    @GetMapping("/updateStatus/{id}/{status}")
    public R updateStatus(@PathVariable Long id, @PathVariable Integer status){
        Product product = new Product();
        product.setId(id);
        product.setStatus(status);
        productService.updateById( product);
        return R.ok();
    }

    //使用redis缓存优化

    //获取商品sku信息
    @GuiguCache
    @InnerAuth
    @GetMapping("/getProductSku/{skuId}")
    R<ProductSku> getProductSku(@PathVariable("skuId") Long skuId){
        ProductSku productSku = productSkuService.getById(skuId);
        return R.ok(productSku);
    }

    //获取商品sku信息,从mysql中查，保证价格是最新的
    @InnerAuth
    @GetMapping("/getProductSkuForCart/{skuId}")
    R<ProductSku> getProductSkuForCart(@PathVariable("skuId") Long skuId){
        ProductSku productSku = productSkuService.getById(skuId);
        return R.ok(productSku);
    }



    //获取商品信息
    @GuiguCache
    @InnerAuth
    @GetMapping("/getProduct/{productId}")
    R<Product> getProduct(@PathVariable("productId") Long productId){
        Product product = productService.getById(productId);
        return R.ok(product);
    }

    //根据skuId获取最新的商品价格
    @GuiguCache
    @InnerAuth
    @GetMapping("/getSkuPrice/{skuId}")
    R<SkuPrice> getSkuPrice(@PathVariable("skuId") Long skuId){
        ProductSku productSku = productSkuService.getById(skuId);
        SkuPrice skuPrice = new SkuPrice();
        skuPrice.setSkuId(skuId);
        skuPrice.setSalePrice(productSku.getSalePrice());
        skuPrice.setMarketPrice(productSku.getMarketPrice());
        return R.ok(skuPrice);
    }

    //根据productId获取商品轮播图列表
    @GuiguCache
    @InnerAuth
    @GetMapping("/getSliderUrlList/{productId}")
    String getSliderUrlList(@PathVariable("productId") Long productId){
        return productService.getById(productId).getSliderUrls();
    }

    //根据productId获取商品详情图片列表
    @GuiguCache
    @InnerAuth
    @GetMapping("/getDetailsimagesUrlList/{productId}")
    String getDetailsimagesUrlList(@PathVariable("productId") Long productId){
        QueryWrapper<ProductDetails> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("product_id", productId);
        return productDetailsService.getOne(queryWrapper).getImageUrls();
    }

    //根据skuId获取商品库存信息
    @GuiguCache()
    @InnerAuth
    @GetMapping("/getSkuStockVo/{skuId}")
    R<SkuStockVo> getSkuStockVo(@PathVariable("skuId") Long skuId){
        SkuStockVo skuStockVo = new SkuStockVo();
        QueryWrapper<SkuStock> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("sku_id", skuId);
        SkuStock skuStock = skuStockService.getOne(queryWrapper);
        skuStockVo.setSkuId(skuId);
        skuStockVo.setSaleNum(skuStock.getSaleNum());
        skuStockVo.setAvailableNum(skuStock.getAvailableNum());
        return R.ok(skuStockVo);
    }

    //根据productId获取商品规格信息
    @GuiguCache
    @InnerAuth
    @GetMapping("/getSkuSpecValueMap/{productId}")
    R<List<ProductSku>> getSkuSpecValueMap(@PathVariable("productId") Long productId){
        QueryWrapper<ProductSku> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("product_id", productId);
        return R.ok(productSkuService.list(queryWrapper));
    }


    //查询购物车商品的最新价格
    @InnerAuth
    @PostMapping("/getSkuPriceList/")
    R<List<ProductSku>> getSkuPriceList(@RequestBody List<Long> skuIdList){
        QueryWrapper<ProductSku> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("id", skuIdList);
        List<ProductSku> list = productSkuService.list(queryWrapper);
        return R.ok(list);
    }

    //校验库存并锁定库存
    @InnerAuth
    @PostMapping("/checkAndLock/{tradeNo}")
    R<String> checkAndLock(@PathVariable("tradeNo") String tradeNo, @RequestBody List<SkuLockVo> skuLockVoList){

        String key = "sku:checkAndLock:" + tradeNo;
        //如果成功锁定库存，就将dataKey保存到redis中
        String dataKey = "sku:lock:data:" + tradeNo;
        //防止重复请求
        Boolean isExist = redisTemplate.opsForValue().setIfAbsent(key, tradeNo, 1, TimeUnit.HOURS);
        if(!isExist){
            if(redisTemplate.opsForValue().get(dataKey) != null){
                return R.ok("");
            }else {
                return R.ok("请勿重复请求");
            }
        }

        //遍历所有商品，验库存并锁库存，要具备原子性
        skuLockVoList.forEach(new Consumer<SkuLockVo>() {
            @Override
            public void accept(SkuLockVo skuLockVo) {
                SkuStock skuStockCheck = skuStockMapper.check(skuLockVo.getSkuId(), skuLockVo.getSkuNum());
                if(skuStockCheck == null) {
                    skuLockVo.setIsHaveStock(false);
                }else {
                    skuLockVo.setIsHaveStock(true);
                }
            }
        });
        // 只要有一个商品锁定失败，所有锁定成功的商品要解锁库存
        boolean hasFailed = skuLockVoList.stream().anyMatch(new Predicate<SkuLockVo>() {
            @Override
            public boolean test(SkuLockVo skuLockVo) {
                return !skuLockVo.getIsHaveStock();
            }
        });

        //分情况是否锁定商品
        if(hasFailed){
            //存在商品锁定失败，全部解锁
            StringBuilder resultMsg = new StringBuilder();
            List<SkuLockVo> hasFailedList = skuLockVoList.stream().filter(skuLockVo -> !skuLockVo.getIsHaveStock()).toList();
            hasFailedList.forEach(skuLockVo -> resultMsg.append("商品: " + skuLockVo.getSkuId() + " 库存不足;"));
            redisTemplate.delete(key);
            return R.ok(resultMsg.toString());
        }
        //不存在商品锁定失败，锁定库存
        skuLockVoList.forEach(new Consumer<SkuLockVo>() {
            @Override
            public void accept(SkuLockVo skuLockVo) {
                int row = skuStockMapper.lock(skuLockVo.getSkuId(), skuLockVo.getSkuNum());
                if (row == 0){
                    redisTemplate.delete(key);
                    throw new RuntimeException("库存锁定失败");
                }
            }
        });
        redisTemplate.opsForValue().set(dataKey, skuLockVoList, 1, TimeUnit.DAYS);
        redisTemplate.delete(key);
        return R.ok("");
    }
}
